use crate::config::app_error::AppResult;
use crate::extension::index::index::indexed_query_engine;
use crate::extension::index::page_request::Sort;
use crate::extension::index::router::list_options::ListOptions;
use crate::extension::index::scheme_manager;
use crate::store::extension_store_client;
use halo_model::{ExtensionOperator, GVK};
use log::{debug, warn};
use std::time::Instant;

pub async fn list_all<T>(struct_type: &str, options: &ListOptions, sort: &Sort) -> AppResult<Vec<T>>
where
    T: for<'de> serde::Deserialize<'de> + ExtensionOperator + GVK,
{
    let (name, scheme) = scheme_manager::get_scheme::<T>().await?;

    let object_keys =
        indexed_query_engine::retrieve_all::<T>(&scheme.group_version_kind, options, sort)?;

    if object_keys.len() > 500 {
        warn!("The number of objects retrieved by listAll is too large ({}) and it is recommended to use paging query.", object_keys.len())
    }

    let store_names = object_keys
        .iter()
        .map(|key| scheme_manager::build_store_name(&scheme, key))
        .collect::<Vec<_>>();

    let start_time = Instant::now();
    let x = extension_store_client::list_by_names::<T>(&store_names).await?;
    debug!(
        "Successfully retrieved all by names from db for {} in {}ms",
        &scheme.group_version_kind,
        start_time.elapsed().as_millis()
    );
    Ok(x)
}
